!--------------------------------------------------------------------------------------------------!
!   CP2K: A general program to perform molecular dynamics simulations                              !
!   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
!                                                                                                  !
!   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
!--------------------------------------------------------------------------------------------------!

! **************************************************************************************************
!> \brief Defines the basic variable types
!> \note
!>      Data type definitions; tested on:
!>          - IBM AIX xlf90
!>          - SGI IRIX  f90
!>          - CRAY T3E  f90
!>          - DEC ALPHA f90
!>          - NAG_F90
!>          - SUN
!>          - HITACHI
!> \par History
!>      Adapted for CP2K by JGH
!> \author Matthias Krack
! **************************************************************************************************
MODULE kinds

   IMPLICIT NONE

   PRIVATE
   PUBLIC :: sp, dp, print_kind_info, dp_size, sp_size, int_size
   PUBLIC :: int_1, int_4, int_8, int_1_size, int_2_size, int_4_size, int_8_size
   PUBLIC :: real_4, real_8, real_4_size, real_8_size
   PUBLIC :: default_string_length, default_path_length, max_line_length

   INTEGER, PARAMETER :: sp = SELECTED_REAL_KIND(6, 30)
   INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(14, 200)
   ! we rely on this (libraries) but do not check this
   INTEGER, PARAMETER :: dp_size = 8, &
                         int_size = BIT_SIZE(0)/8, &
                         sp_size = 4

   INTEGER, PARAMETER :: real_4 = SELECTED_REAL_KIND(6, 30)
   INTEGER, PARAMETER :: real_8 = SELECTED_REAL_KIND(14, 200)
   INTEGER, PARAMETER :: real_4_size = 4
   INTEGER, PARAMETER :: real_8_size = 8

   INTEGER, PARAMETER :: int_1 = SELECTED_INT_KIND(2)
   INTEGER, PARAMETER :: int_1_size = BIT_SIZE(INT(0, int_1))/8

   INTEGER, PARAMETER :: int_2 = SELECTED_INT_KIND(4)
   INTEGER, PARAMETER :: int_2_size = BIT_SIZE(INT(0, int_2))/8

   INTEGER, PARAMETER :: int_4 = SELECTED_INT_KIND(5)
   INTEGER, PARAMETER :: int_4_size = BIT_SIZE(INT(0, int_4))/8

   INTEGER, PARAMETER :: int_8 = SELECTED_INT_KIND(10)
   INTEGER, PARAMETER :: int_8_size = BIT_SIZE(INT(0, int_8))/8

   INTEGER, PARAMETER :: default_string_length = 80
   INTEGER, PARAMETER :: default_path_length = 1024
   INTEGER, PARAMETER :: max_line_length = 2*default_path_length
   CHARACTER(LEN=1), PARAMETER, PUBLIC :: default_blank_character(2) = [" ", CHAR(9)]

CONTAINS

! **************************************************************************************************
!> \brief Print informations about the used data types.
!> \param iw ...
!> \par History
!>      Adapted by JGH for Cp2k
!> \author Matthias Krack
! **************************************************************************************************
   SUBROUTINE print_kind_info(iw)

      INTEGER, INTENT(IN)                                :: iw

      WRITE (iw, '( /, T2, A )') 'DATA TYPE INFORMATION:'

      WRITE (iw, '( /,T2,A,T79,A,2(/,T2,A,T75,I6),3(/,T2,A,T67,E14.8) )') &
         'REAL: Data type name:', 'dp', '      Kind value:', KIND(0.0_dp), &
         '      Precision:', PRECISION(0.0_dp), &
         '      Smallest non-negligible quantity relative to 1:', &
         EPSILON(0.0_dp), &
         '      Smallest positive number:', TINY(0.0_dp), &
         '      Largest representable number:', HUGE(0.0_dp)
      WRITE (iw, '( /,T2,A,T79,A,2(/,T2,A,T75,I6),3(/,T2,A,T67,E14.8) )') &
         '      Data type name:', 'sp', '      Kind value:', KIND(0.0_sp), &
         '      Precision:', PRECISION(0.0_sp), &
         '      Smallest non-negligible quantity relative to 1:', &
         EPSILON(0.0_sp), &
         '      Smallest positive number:', TINY(0.0_sp), &
         '      Largest representable number:', HUGE(0.0_sp)
      WRITE (iw, '( /,T2,A,T72,A,4(/,T2,A,T61,I20) )') &
         'INTEGER: Data type name:', '(default)', '         Kind value:', &
         KIND(0), &
         '         Bit size:', BIT_SIZE(0), &
         '         Largest representable number:', HUGE(0)
      WRITE (iw, '( /,T2,A,T72,A,/,T2,A,T75,I6,/ )') &
         'LOGICAL: Data type name:', '(default)', &
         '         Kind value:', KIND(.TRUE.)
      WRITE (iw, '( /,T2,A,T72,A,/,T2,A,T75,I6,/ )') &
         'CHARACTER: Data type name:', '(default)', &
         '           Kind value:', KIND('C')

   END SUBROUTINE print_kind_info

END MODULE kinds
